home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / dm3_src.zip / DMCOMMIO.ASM < prev    next >
Assembly Source File  |  1990-04-26  |  58KB  |  1,638 lines

  1.  
  2. ;* ************************************************************************* *;
  3. ;*                                                                           *;
  4. ;*               M Y C R O F T   D M   L I B R A R Y   3 . 0 0               *;
  5. ;*                     Low Level Comm Port I/O Functions                     *;
  6. ;*                                                                           *;
  7. ;* ************************************************************************* *;
  8.  
  9.  
  10. ;==========================
  11. ; User Defined Definitions
  12. ;==========================
  13.  
  14. ; Note:  The buffer sizes must be an even power of 2 (ie. 32, 64, 1024, etc).
  15. ;        An input buffer of 16 to 64 and an output buffer of 64 to 512
  16. ;        should be fine for normal door use.  Suggest 2K for both input and
  17. ;        and output buffers for doors doing large data transfers such as
  18. ;        file uploads and downloads.
  19. ;
  20. ;        If the DCDW flag is set then the _comm_regs function will need to
  21. ;        be called to monitor DCD.  All other functions will then ignore DCD
  22. ;        and will never return a status indicating it has been lost.
  23. ;
  24. ;        In general, for door applications, DCDW should be set to 0.  STAW
  25. ;        may also be set to 0 as there is little you can do in a door in the
  26. ;        event of line errors.
  27. ;
  28.  
  29. DCDW            equ     0               ; 1 for ignoring loss of DCD
  30. STAW            equ     0               ; 1 for monitoring STAT register
  31.  
  32. IBUFFSIZE       equ     64              ; Size of input buffer
  33. IBUFFMASK       equ     IBUFFSIZE - 1   ; Circular mask for input buffer
  34. IBUFFFULL       equ     IBUFFSIZE - 16  ; Limit to to take down RTS
  35. OBUFFSIZE       equ     1024            ; Size of output buffer
  36. OBUFFMASK       equ     OBUFFSIZE - 1   ; Circular mask for input buffer
  37. OBUFFFULL       equ     OBUFFSIZE - 16  ; Limit to wait for empty spot
  38.  
  39.  
  40.  
  41. ;==========================
  42. ;  BIOS/Fossil Definitions
  43. ;==========================
  44.  
  45. BIOS    equ     14H                     ; BIOS Comm interrupt
  46.  
  47. BCBAUD  equ     00H                     ; Setup comm port function
  48. BCOUT   equ     01H                     ; Output to comm port function
  49. BCIN    equ     02H                     ; Input from comm port function
  50. BCSTAT  equ     03H                     ; Return I/O status registers
  51. BCINIT  equ     04H                     ; Initialize Fossil
  52. BCWAIT  equ     08H                     ; Wait for output complete
  53. BCFOUT  equ     09H                     ; Flush output buffer
  54. BCFIN   equ     0AH                     ; Flush input buffer
  55.  
  56. BCTIME  equ     80H                     ; Timeout flag
  57.  
  58.  
  59. ;==========================
  60. ;  Comm Port Definitions
  61. ;==========================
  62.  
  63. DATA    equ     00H                     ; data port offset
  64.  
  65. EINT    equ     01H                     ; interrupt enable offset
  66. EIMS    equ     08H                     ; enable modem status int
  67. IF STAW ;*********************************************************************
  68. EILS    equ     04H                     ; enable line status int
  69. ELSE
  70. EILS    equ     00H                     ; do not enable line status int
  71. ENDIF   ;*********************************************************************
  72. EITX    equ     02H                     ; enable tx ready int
  73. EIRX    equ     01H                     ; enable RX avail int
  74.  
  75. IINT    equ     02H                     ; interrupt identification
  76. IIMK    equ     06H                     ; interrupt id mask
  77. IIPD    equ     01H                     ; interrupt pending flag
  78.  
  79. LCRR    equ     03H                     ; line control register
  80.  
  81. MCRR    equ     04H                     ; modem control register
  82. MCLP    equ     10H                     ; loop back test
  83. MCO2    equ     08H                     ; out2 control
  84. MCO1    equ     04H                     ; out1 control
  85. MCRT    equ     02H                     ; RTS control
  86. MCDT    equ     01H                     ; DTR control
  87.  
  88. STAT    equ     05H                     ; line status register
  89. STTX    equ     40H                     ; TX empty
  90. STTH    equ     20H                     ; TH empty
  91. STBK    equ     10H                     ; BREAK detected
  92. STFE    equ     08H                     ; framing error
  93. STPE    equ     04H                     ; parity error
  94. STOE    equ     02H                     ; overrun error
  95. STRX    equ     01H                     ; RX available
  96.  
  97. MODM    equ     06H                     ; modem status register
  98. MODC    equ     80H                     ; DCD status
  99. MORI    equ     40H                     ; ring indicator
  100. MODS    equ     20H                     ; DSR status
  101. MOCT    equ     10H                     ; CTS status
  102.  
  103.  
  104.  
  105. ;==========================
  106. ;   Interrupt Controller
  107. ;       Definitions
  108. ;==========================
  109.  
  110. IRQ0    equ     01H                     ; interrupt mask for IRQ0
  111. IRQ1    equ     02H                     ; interrupt mask for IRQ1
  112. IRQ2    equ     04H                     ; interrupt mask for IRQ2
  113. IRQ3    equ     08H                     ; interrupt mask for IRQ3
  114. IRQ4    equ     10H                     ; interrupt mask for IRQ4
  115. IRQ5    equ     20H                     ; interrupt mask for IRQ5
  116. IRQ6    equ     40H                     ; interrupt mask for IRQ6
  117. IRQ7    equ     80H                     ; interrupt mask for IRQ7
  118. IRQ0V   equ     8                       ; interrupt vector for IRQ0
  119. IRQ1V   equ     9                       ; interrupt vector for IRQ1
  120. IRQ2V   equ     10                      ; interrupt vector for IRQ2
  121. IRQ3V   equ     11                      ; interrupt vector for IRQ3
  122. IRQ4V   equ     12                      ; interrupt vector for IRQ4
  123. IRQ5V   equ     13                      ; interrupt vector for IRQ5
  124. IRQ6V   equ     14                      ; interrupt vector for IRQ6
  125. IRQ7V   equ     15                      ; interrupt vector for IRQ7
  126.  
  127.  
  128. EOIP    equ     20H                     ; EOI port
  129. EOIP2   equ    0A0H                     ; EOI port
  130.  
  131. IEOI    equ     00H                     ; Interrupt EOI port
  132. IMSK    equ     01H                     ; Interrupt mask port
  133.  
  134. EOID    equ     20H                     ; EOI data
  135.  
  136.  
  137. ;==========================
  138. ;      DOS Interface
  139. ;       Definitions
  140. ;==========================
  141.  
  142. DOS             equ     21H             ; DOS access vector
  143.  
  144. DOS_SET_VECTOR  equ     25H             ; Set interrupt vector
  145. DOS_GET_VECTOR  equ     35H             ; Get interrupt vector
  146.  
  147.  
  148. ;==========================
  149. ;  Character Definitions
  150. ;==========================
  151.  
  152. XON             equ     11H             ; XON character
  153. XOFF            equ     13H             ; XOFF character
  154.  
  155.  
  156. ;==========================
  157. ;    Comm Port Monitor
  158. ;     For DM Library
  159. ;==========================
  160.  
  161. DMIOSEG SEGMENT 'CODE'
  162. ASSUME  cs:DMIOSEG
  163.  
  164.  
  165. ;==========================
  166. ;    Linkage References
  167. ;==========================
  168.  
  169. public  _dmcomm_init
  170. public  _dmcomm_release
  171. public  _dmcomm_status
  172. public  _dmcomm_regs
  173. public  _dmcomm_input
  174. public  _dmcomm_output
  175. public  _dmcomm_wait
  176. public  _dmcomm_iflush
  177. public  _dmcomm_oflush
  178.  
  179.  
  180. ;==========================
  181. ;       Local Storage
  182. ;==========================
  183.  
  184. commid  dw      0                       ; logical comm port number to use
  185. cport   dw      0                       ; comm port physical address
  186. iport   dw      20H                     ; 8259A port to use
  187. cirqm   db      0                       ; IRQ mask to use
  188. cirqv   db      0                       ; IRQ vector to use
  189. usint   dw      0                       ; use interrupts flag
  190. handsh  dw      0                       ; handshake to use
  191. passth  dw      0                       ; passthrough the interrupt
  192.  
  193. clstat  db      0                       ; last line status
  194. cmstat  db      0                       ; last modem status
  195.  
  196. isave   db      0                       ; 8259A inetrrupt mask save
  197. sisave  db      0                       ; serial interrupt mask save
  198. smsave  db      0                       ; serial modem control mask save
  199.  
  200. oldint  dw      offset _dmcomm_isr      ; old interrupt vector
  201.         dw      seg _dmcomm_isr
  202.  
  203. ibuffer db      IBUFFSIZE dup (0)       ; input buffer
  204. iputptr dw      0                       ; input put pointer
  205. igetptr dw      0                       ; input get pointer
  206. icount  dw      0                       ; number of chars in buffer
  207.  
  208. obuffer db      OBUFFSIZE dup (0)       ; output buffer
  209. oputptr dw      0                       ; output put pointer
  210. ogetptr dw      0                       ; output get pointer
  211. ocount  dw      0                       ; number of chars in buffer
  212.  
  213. count1  dw      0                       ; counter no. 1 for timeouts
  214. count2  dw      0                       ; counter no. 2 for timeouts
  215.  
  216. no_carrier      db      0               ; carrier lost
  217. no_cts          db      0               ; CTS lost
  218. no_rts          db      0               ; RTS taken down
  219. no_xon          db      0               ; Have received a XOFF
  220. no_xoff         db      0               ; Have sent an XOFF
  221. prime           db      1               ; prime required
  222.  
  223.  
  224. isr_table       label word              ; Table of isr service routines
  225.         dw      offset comm_modem       ; modem status routine
  226.         dw      offset comm_tx          ; TX buffer empty routine
  227.         dw      offset comm_rx          ; RX data available routine
  228.         dw      offset comm_line        ; line status routine
  229.  
  230.  
  231. ;==========================
  232. ;      Code Section
  233. ;==========================
  234.  
  235. _dmcomm_init    proc    far
  236. ;
  237. ;==========================
  238. ; Comm Port Initialization
  239. ;==========================
  240. ; Procedure:    1. Save the passed parameters
  241. ;               2. Init flags & pointers
  242. ;               3. Save old hardware settings
  243. ;               4. Save old interrupt vectors
  244. ;               5. If int driven then set new vectors
  245. ;               6. Setup new hardware masks
  246. ;               7. Force RTS to allow data flow
  247. ;               8. Exit all done
  248. ; Entry:        BP+6 : Port Value for i/o port (hex address) (8250 assumed)
  249. ;               BP+8 : Port Value for i/o port (hex address) (8250 assumed)
  250. ;               BP+10: IRQ Number to use for port (0-7) (8259A assumed)
  251. ;               BP+12: Access control flag (0=BIOS/Fossil, 1=Direct access,
  252. ;                                           2=Interrupt driven)
  253. ;               BP+14: Handshake control flag (0=None,    1=XON/XOFF,
  254. ;                                              2=RTS/CTS, 3=BOTH)
  255. ;               BP+16: Interrupt passthrough  (0=No, 1=Yes)
  256. ; Return:       AX = -1 if error
  257. ;               AX =  0 if init processed ok
  258. ;
  259.  
  260. ;
  261. ; Access the stack frame
  262. ;
  263.         push    bp                      ; save c stack frame
  264.         mov     bp,sp
  265.         push    es                      ; save environment
  266.         push    ds
  267.         push    di
  268.         push    si
  269.         mov     ax,cs                   ; point to data
  270.         mov     ds,ax
  271. ;
  272. ; Save configuration
  273. ;
  274.         mov     ax,[bp+6]               ; store the comm port id
  275.         mov     commid,ax
  276.         mov     ax,[bp+8]               ; store the comm port base address
  277.         mov     cport,ax
  278. ;
  279.         mov     ax,[bp+10]              ; compute interrupt vector address
  280.         cmp     ax,7                    ; test if valid
  281.         jbe     comm_init_00
  282. comm_init_err:
  283.         mov     ax,-1                   ; flag error
  284.         jmp     comm_init_done          ; exit
  285. ;
  286. comm_init_00:
  287.         add     ax,IRQ0V
  288.         mov     cirqv,al
  289.         mov     ax,1                    ; compute interrupt mask
  290.         mov     cx,[bp+10]
  291.         or      cl,cl
  292.         jz      comm_init_10
  293.         shl     ax,cl
  294. comm_init_10:
  295.         mov     cirqm,al
  296. ;
  297.         mov     ax,[bp+12]              ; store access control flag
  298.         cmp     ax,2
  299.         ja      comm_init_err           ; flag it if error
  300.         mov     usint,ax
  301. ;
  302.         mov     ax,[bp+14]              ; store handshake control flag
  303.         cmp     ax,3
  304.         ja      comm_init_err           ; flag it if error
  305.         mov     handsh,ax
  306. ;
  307.         mov     ax,[bp+16]              ; store interrupt passthrough flag
  308.         cmp     ax,1
  309.         ja      comm_init_err           ; flag it if error
  310.         mov     passth,ax
  311. ;
  312. ; Init buffer flags and pointers
  313. ;
  314.         mov     iputptr,0               ; input put pointer
  315.         mov     igetptr,0               ; input get pointer
  316.         mov     icount,0                ; buffer is empty
  317.         mov     oputptr,0               ; output put pointer
  318.         mov     ogetptr,0               ; output get pointer
  319.         mov     ocount,0                ; buffer is empty
  320. ;
  321.         mov     count1,0                ; clear counters
  322.         mov     count2,0                ; clear counters
  323. ;
  324.         mov     no_carrier,0            ; carrier lost
  325.         mov     no_cts,0                ; CTS lost
  326.         mov     no_rts,0                ; RTS taken down
  327.         mov     no_xon,0                ; Have received a XOFF
  328.         mov     no_xoff,0               ; Have sent an XOFF
  329.         mov     prime,1                 ; prime required
  330. ;
  331. ; Save 8255 int flags, comm port flags, and int vector
  332. ;
  333.         cli                             ; Keep the world quiet
  334.         mov     dx,iport                ; Save the 8259 INT flags
  335.         add     dx,IMSK
  336.         in      al,dx
  337.         mov     isave,al
  338. ;
  339.         mov     bx,cport                ; Base port
  340.         mov     dx,bx                   ; Save the 8250 INT flags
  341.         add     dx,EINT
  342.         in      al,dx
  343.         mov     sisave,al
  344.         mov     dx,bx                   ; Save the 8250 Modem flags
  345.         add     dx,MCRR
  346.         in      al,dx
  347.         mov     smsave,al
  348. ;
  349.         mov     ah,DOS_GET_VECTOR       ; Save original interrupt vectors
  350.         mov     al,cirqv
  351.         int     DOS
  352.         mov     word ptr oldint,bx
  353.         mov     word ptr oldint+2,es
  354. ;
  355. ; Get initial values for line and modem status
  356. ;
  357.         cli                             ; Keep the world quiet
  358. IF STAW ;*********************************************************************
  359.         mov     dx,cport                ; get line status port
  360.         add     dx,STAT
  361.         in      al,dx                   ; get the data
  362. ELSE
  363.         mov     al,STTX+STTH            ; not monitoring, set it always ok
  364. ENDIF   ;*********************************************************************
  365.         mov     clstat,al               ; save it
  366.         mov     dx,cport                ; get line status port
  367.         add     dx,MODM
  368.         in      al,dx                   ; get the data
  369.         mov     cmstat,al               ; save it
  370. ;
  371. ; If int driven, Redirect ints to ISR
  372. ;
  373.         cmp     usint,2                 ; Test if interrupt driven
  374.         jne     comm_init_20            ; Skip if not
  375. ;
  376.         push    ds
  377.         mov     ax,SEG _dmcomm_isr
  378.         mov     ds,ax
  379.         mov     dx,OFFSET _dmcomm_isr
  380.         mov     ah,DOS_SET_VECTOR       ; Save original interrupt vectors
  381.         mov     al,cirqv
  382.         int     DOS
  383.         pop     ds
  384. ;
  385. ; If int driven, Adjust masks in 8250 and 8259A
  386. ;
  387.         cli                             ; Keep the world quiet
  388.         mov     dx,iport                ; Set the 8259 INT flag for appropriate
  389.         add     dx,IMSK
  390.         in      al,dx
  391.         mov     ah,cirqm
  392.         xor     ah,0FFH
  393.         and     al,ah
  394.         out     dx,al
  395. ;
  396.         mov     dx,cport                ; Set the 8250 INT flags
  397.         add     dx,EINT
  398.         mov     al,EIRX+EITX+EILS+EIMS
  399.         out     dx,al
  400.         jmp     comm_init_30            ; Now finish up
  401. ;
  402. ; Else Clear masks in 8250
  403. ;
  404. comm_init_20:
  405. ;
  406.         mov     dx,cport                ; Clear the 8250 INT flags
  407.         add     dx,EINT
  408.         mov     al,0
  409.         out     dx,al
  410. ;
  411. ; Set DTR & RTS to allow incomming data
  412. ;
  413.         mov     dx,cport                ; Set DTR & RTS to allow data
  414.         add     dx,MCRR
  415.         mov     al,MCRT+MCDT
  416.         out     dx,al
  417.         jmp     comm_init_done
  418. ;
  419. ; Set DTR & RTS & OUT2 to allow incomming data & interrupts
  420. ;
  421. comm_init_30:
  422.         mov     dx,cport                ; Set DTR & RTS to allow data
  423.         add     dx,MCRR
  424.         mov     al,MCRT+MCDT+MCO2
  425.         out     dx,al
  426. ;
  427. ; Now guarantee all interrupts are cleared
  428. ;
  429. comm_init_40:
  430.         nop                             ; Allow a little time
  431.         nop
  432.         mov     dx,cport                ; Clear modem status
  433.         add     dx,MODM
  434.         nop                             ; Allow a little time
  435.         nop
  436.         in      al,dx
  437.         mov     dx,cport                ; Clear line status
  438.         add     dx,STAT
  439.         nop                             ; Allow a little time
  440.         nop
  441.         in      al,dx
  442.         mov     dx,cport                ; Clear RX available
  443.         add     dx,DATA
  444.         nop                             ; Allow a little time
  445.         nop
  446.         in      al,dx
  447.         mov     dx,cport                ; Clear TX empty
  448.         add     dx,IINT
  449.         nop                             ; Allow a little time
  450.         nop
  451.         in      al,dx
  452.         and     al,IIPD                 ; Loop if still pending
  453.         jz      comm_init_40
  454. ;
  455. ; Init the Fossil if present
  456. ;
  457.         cmp     usint,0                 ; dispatch
  458.         ja      comm_init_done
  459. ;
  460. ; Call Fossil
  461. ;
  462.         mov     ah,BCINIT               ; init the driver
  463.         mov     dx,commid               ; get port id
  464.         mov     bx,0                    ; no ^C trapping
  465.         int     BIOS                    ; do it
  466. ;
  467. ; Exit all done
  468. ;
  469. comm_init_done:
  470.         sti                             ; Bring the world back to life
  471.         pop     si                      ; restore registers
  472.         pop     di
  473.         pop     ds
  474.         pop     es
  475.         pop     bp                      ; clear out stack frame
  476.         ret
  477. ;
  478. _dmcomm_init    endp
  479.  
  480.  
  481. _dmcomm_release proc    far
  482. ;
  483. ;==========================
  484. ;     Comm Port Release
  485. ;==========================
  486. ; Procedure:    1. Restore old hardware settings
  487. ;               2. Restore INT vector
  488. ;               3. Exit all done
  489. ; Entry:        None
  490. ; Return:       None
  491. ;
  492.         push    es                      ; Save
  493.         push    ds
  494.         push    di
  495.         push    si
  496.         mov     ax,cs                   ; Access local storage
  497.         mov     ds,ax
  498.         cli                             ; Keep the world quiet
  499. ;
  500. ; Restore 8255 int flags, comm port flags, and int vector
  501. ;
  502.         mov     dx,iport                ; Restore the 8259 INT flags
  503.         add     dx,IMSK
  504.         mov     al,isave
  505.         out     dx,al
  506. ;
  507.         mov     bx,cport                ; Base port
  508.         mov     dx,bx                   ; Save the 8250 INT flags
  509.         add     dx,EINT
  510.         mov     al,sisave
  511.         out     dx,al
  512.         mov     dx,bx                   ; Save the 8250 Modem flags
  513.         add     dx,MCRR
  514.         mov     al,smsave
  515.         out     dx,al
  516. ;
  517.         mov     dx,word ptr [oldint]
  518.         mov     bx,word ptr [oldint+2]
  519.         mov     ah,DOS_SET_VECTOR       ; Save original interrupt vectors
  520.         mov     al,cirqv
  521.         mov     ds,bx
  522.         int     DOS
  523. ;
  524. ; Exit all done
  525. ;
  526.         sti                             ; Alive once again
  527.         pop     si                      ; restore registers
  528.         pop     di
  529.         pop     ds
  530.         pop     es
  531.         ret
  532. ;
  533. _dmcomm_release endp
  534.  
  535.  
  536. _dmcomm_status  proc    far
  537. ;
  538. ;==========================
  539. ;     Comm Port Status
  540. ;==========================
  541. ; Procedure:    1. If interrupts enabled goto 6
  542. ;               2. Read modem status
  543. ;               3. Return -1 if no carrier
  544. ;               4. Read line status
  545. ;               5. Return char available status
  546. ;               6. Return -1 if no carrier
  547. ;               7. Test input pointers
  548. ;               8. Return char available status
  549. ; Entry:        None
  550. ; Return:       AX = -1 if loss of carrier
  551. ;               AX =  0 if no data available
  552. ;               AX =  1 if character available
  553. ;
  554.         push    es                      ; save callers regs
  555.         push    ds
  556.         push    di
  557.         push    si
  558.         mov     ax,cs                   ; point to storage
  559.         mov     ds,ax
  560. ;
  561. ; Dispatch based on access
  562. ;
  563.         cmp     usint,1                 ; dispatch
  564.         je      comm_status_10
  565.         ja      comm_status_50
  566. ;
  567. ; Call BIOS/Fossil
  568. ;
  569. comm_status_00:
  570.         mov     ah,BCSTAT               ; read the registers
  571.         mov     dx,commid               ; get port id
  572.         int     BIOS                    ; get the status
  573. IF DCDW ;*********************************************************************
  574.         jmp     comm_status_02          ; DCDW: skip DCD test
  575. ENDIF   ;*********************************************************************
  576.         and     al,MODC                 ; test for carrier
  577.         jnz     comm_status_02
  578.         mov     no_carrier,1            ; flag no carrier
  579.         mov     ax,-1
  580.         jmp     comm_status_90          ; and exit
  581. ;
  582. comm_status_02:
  583.         mov     al,0                    ; assume no character
  584.         and     ah,STRX                 ; test if data available
  585.         jz      comm_status_04          ; exit all done if no char
  586.         mov     ax,1                    ; else flag char available
  587. comm_status_04:
  588.         jmp     comm_status_90          ; exit all done
  589. ;
  590. ; Read ports directly
  591. ;
  592. comm_status_10:
  593. IF DCDW ;*********************************************************************
  594.         jmp     comm_status_20          ; DCDW: skip DCD test
  595. ENDIF   ;*********************************************************************
  596.         mov     dx,cport                ; get base port
  597.         add     dx,MODM                 ; get modem status
  598.         in      al,dx
  599.         and     al,MODC                 ; test for carrier
  600.         jnz     comm_status_20
  601.         mov     no_carrier,1            ; flag no carrier
  602.         mov     ax,-1
  603.         jmp     comm_status_90          ; and exit
  604. ;
  605. comm_status_20:
  606.         mov     dx,cport                ; get base port
  607.         add     dx,STAT                 ; get line status
  608.         in      al,dx
  609.         and     al,STRX
  610.         jz      comm_regs_90            ; exit all done if no char
  611.         mov     ax,1                    ; else flag char available
  612.         jmp     comm_regs_90            ; exit all done
  613. ;
  614. ; Read last stored values
  615. ;
  616. comm_status_50:
  617.         cli                             ; freeze the system
  618.         cmp     no_carrier,1            ; test for carrier
  619.         jne     comm_status_60          ; continue if carrier exists
  620.         mov     ax,-1                   ; else flag no carrier
  621.         sti                             ; alive again
  622.         jmp     comm_status_90          ; and exit
  623. ;
  624. comm_status_60:
  625.         cmp     icount,0                ; test if empty
  626.         sti                             ; alive again
  627.         mov     ax,0                    ; assume no data avail
  628.         je      comm_status_90          ; exit if none avail
  629.         inc     ax                      ; else flag character available
  630. ;
  631. ; Restore regs & exit
  632. ;
  633. comm_status_90:
  634.         pop     si                      ; restore registers
  635.         pop     di
  636.         pop     ds
  637.         pop     es
  638.         ret                             ; return to caller
  639. ;
  640. _dmcomm_status  endp
  641.  
  642.  
  643. _dmcomm_regs    proc    far
  644. ;
  645. ;==========================
  646. ;  Comm Port Status Regs
  647. ;==========================
  648. ; Procedure:    1. If using ints, get stored values
  649. ;               2. Else read port values
  650. ;               3. exit
  651. ; Entry:        None
  652. ; Return:       AH = Line Status
  653. ;               AL = Modem status
  654. ;
  655.         push    es                      ; save callers regs
  656.         push    ds
  657.         push    di
  658.         push    si
  659.         mov     ax,cs                   ; point to storage
  660.         mov     ds,ax
  661. ;
  662. ; Dispatch based on access type
  663. ;
  664.         cmp     usint,1                 ; dispatch
  665.         je      comm_regs_10
  666.         ja      comm_regs_50
  667. ;
  668. ; Read regs via the BIOS/Fossil
  669. ;
  670. comm_regs_00:
  671.         mov     ah,BCSTAT               ; read the registers
  672.         mov     dx,commid               ; get port id
  673.         int     BIOS                    ; get the status
  674.         jmp     comm_regs_90            ; exit all done
  675. ;
  676. ; Read ports directly
  677. ;
  678. comm_regs_10:
  679.         mov     dx,cport                ; get base port
  680.         add     dx,STAT                 ; get line status
  681.         in      al,dx
  682.         mov     ah,al                   ; it is returned in AH
  683.         mov     dx,cport                ; get base port
  684.         add     dx,MODM                 ; get control status
  685.         in      al,dx                   ; it is returned in AL
  686.         jmp     comm_regs_90            ; exit all done
  687. ;
  688. ; Read last stored values
  689. ;
  690. comm_regs_50:
  691.         cli                             ; freeze the system
  692.         mov     ah,clstat               ; get last line status
  693.         mov     al,cmstat               ; get last modem status
  694.         sti                             ; alive again
  695. ;
  696. ; Restore regs & exit
  697. ;
  698. comm_regs_90:
  699.         pop     si                      ; restore registers
  700.         pop     di
  701.         pop     ds
  702.         pop     es
  703.         ret                             ; return to caller
  704. ;
  705. _dmcomm_regs    endp
  706.  
  707.  
  708. _dmcomm_input   proc    far
  709. ;
  710. ;==========================
  711. ;     Comm Port Input
  712. ;==========================
  713. ; Procedure:    1. If interrupt driven goto 6
  714. ;               2. Test port status
  715. ;               3. Return -1 if no carrier
  716. ;               4. If no character goto 2
  717. ;               5. Read & return character
  718. ;               6. If no carrier then return -1
  719. ;               7. If pointers are equal goto 6
  720. ;               8. Get character
  721. ;               9. Adjust pointers
  722. ;              10. If RTS down bring it back
  723. ;              11. Return character
  724. ; Entry:        None
  725. ; Return:       AX = -1 if no carrier
  726. ;               AX = character otherwise
  727. ;
  728.         push    es                      ; save callers registers
  729.         push    ds
  730.         push    di
  731.         push    si
  732.         mov     ax,cs                   ; point to storage
  733.         mov     ds,ax
  734. ;
  735. ; Dispatch based on access type
  736. ;
  737.         cmp     usint,1                 ; dispatch
  738.         je      comm_input_10
  739.         ja      comm_input_50
  740. ;
  741. ; Access the BIOS/Fossil driver
  742. ;
  743. comm_input_00:
  744.         call    _dmcomm_status          ; test if character available
  745.         cmp     ax,-1                   ; no carrier?
  746.         je      comm_input_02           ; exit if so
  747.         cmp     al,1                    ; char available
  748.         jne     comm_input_00           ; loop if not
  749. ;
  750.         mov     ah,BCIN                 ; input a character
  751.         mov     dx,commid               ; get port id
  752.         int     BIOS                    ; get the status
  753. comm_input_02:
  754.         jmp     comm_input_90           ; exit with the character
  755. ;
  756. ; Read port info directly
  757. ;
  758. comm_input_10:
  759.         call    _dmcomm_status          ; test if character available
  760.         cmp     ax,-1                   ; no carrier?
  761.         je      comm_input_90           ; exit if so
  762.         cmp     al,1                    ; char available
  763.         jne     comm_input_10           ; loop if not
  764. ;
  765.         mov     dx,cport                ; get base port
  766.         add     dx,DATA                 ; index to data
  767.         in      al,dx                   ; read the character
  768.         jmp     comm_input_90           ; exit with the character
  769. ;
  770. ; Else test the pointers & flags
  771. ;
  772. comm_input_50:
  773.         cli                             ; freeze the world
  774.         cmp     no_carrier,1            ; carrier lost ?
  775.         jne     comm_input_60           ; continue if not
  776.         sti                             ; alive again
  777.         mov     ax,-1                   ; flag loss of carrier
  778.         jmp     comm_input_90           ; and exit
  779. ;
  780. comm_input_60:
  781.         mov     bx,igetptr              ; get pointer
  782.         cmp     icount,0                ; test if empty
  783.         jne     comm_input_70           ; continue if not (char available)
  784.         sti                             ; alive again
  785.         nop                             ; some delay
  786.         nop
  787.         nop
  788.         jmp     comm_input_50           ; try again
  789. ;
  790. comm_input_70:
  791.         lea     si,ibuffer              ; point to buffer
  792.         mov     al,[si][bx]             ; get the data
  793.         mov     ah,0                    ; clear upper value
  794. ;
  795.         inc     bx                      ; adjust pointer
  796.         and     bx,IBUFFMASK
  797.         mov     igetptr,bx              ; save new value
  798.         dec     icount
  799.         sti
  800. ;
  801.         cmp     no_rts,1                ; RTS down?
  802.         jne     comm_input_80           ; exit if done
  803.         cli
  804.         mov     bx,ax                   ; save input
  805.         mov     dx,cport                ; get base port
  806.         add     dx,MCRR
  807.         mov     al,MCRT+MCDT+MCO2       ; bring RTS back up
  808.         out     dx,al
  809.         mov     no_rts,0                ; and flag as up
  810.         sti
  811. ;
  812. comm_input_80:
  813.         cmp     no_xoff,1               ; paused?
  814.         jne     comm_input_82           ; skip if not
  815.         mov     al,XON                  ; else bring up input
  816.         call    comm_char
  817. ;
  818. comm_input_82:
  819. ;
  820. ; Restore regs & exit
  821. ;
  822. comm_input_90:
  823.         pop     si                      ; restore registers
  824.         pop     di
  825.         pop     ds
  826.         pop     es
  827.         ret                             ; return to caller
  828. ;
  829. _dmcomm_input   endp
  830.  
  831.  
  832. _dmcomm_output  proc    far
  833. ;
  834. ;==========================
  835. ;     Comm Port Output
  836. ;==========================
  837. ; Procedure:    1. If no carrier then abort
  838. ;               2. If interrupt driven then goto 11
  839. ;               3. Test for TX buffer empty
  840. ;               4. Goto 3 if not empty
  841. ;               5. Test for CTS active
  842. ;               6. Goto 5 if not active
  843. ;               7. Output character & exit
  844. ;               8. Test if prime flag set
  845. ;               9. Goto 11 if not
  846. ;              10. Output character & exit
  847. ;              11. Test if prime required
  848. ;              12. Goto 3 if so
  849. ;              13. Test if space available in out put buffer
  850. ;              14. Goto 13 if none
  851. ;              15. Store character in output buffer
  852. ;              16. Adjust pointers & exit
  853. ; Entry:        [BP+6] = character to output
  854. ; Return:       AX = -1 if no carrier
  855. ;               AX = 0 if all ok
  856. ;               AX = 1 if timeout
  857. ;
  858.         push    bp                      ; setup stack frame
  859.         mov     bp,sp
  860.         push    es                      ; save callers registers
  861.         push    ds
  862.         push    di
  863.         push    si
  864.         mov     ax,cs                   ; access storage
  865.         mov     ds,ax
  866. ;
  867. ; Dispatch based on access type
  868. ;
  869.         cmp     usint,1                 ; dispatch
  870.         jb      comm_output_00
  871.         je      comm_output_05
  872.         jmp     comm_output_50
  873. ;
  874. ; Process via BIOS/Fossil
  875. ;
  876. comm_output_00:
  877. IF DCDW ;*********************************************************************
  878.         jmp     comm_output_02          ; DCDW: skip DCD test
  879. ENDIF   ;*********************************************************************
  880.         mov     ah,BCSTAT               ; read the registers
  881.         mov     dx,commid               ; get port id
  882.         int     BIOS                    ; get the status
  883.         and     al,MODC                 ; test for carrier
  884.         jnz     comm_output_02
  885.         mov     ax,-1                   ; flag as no carrier
  886.         jmp     comm_output_90          ; and exit
  887. comm_output_02:
  888.         mov     ax,[bp+6]               ; get the character
  889.         mov     ah,BCOUT                ; output a character
  890.         mov     dx,commid               ; get port id
  891.         int     BIOS                    ; get the status
  892.         mov     al,0                    ; assume all went well
  893.         and     ah,BCTIME               ; test for timeout
  894.         jz      comm_output_04
  895.         mov     ax,1                    ; flag the timeout
  896. comm_output_04:
  897.         jmp     comm_output_90          ; exit all done
  898. ;
  899. ; Read ports directly
  900. ;
  901. comm_output_05:
  902.         call    time_start              ; full max allowed
  903.         mov     dx,cport                ; get base port
  904.         add     dx,MODM
  905. comm_output_10:
  906. IF DCDW ;*********************************************************************
  907.         jmp     comm_output_15          ; DCDW: skip DCD test
  908. ENDIF   ;*********************************************************************
  909.         cli
  910.         in      al,dx                   ; get current status
  911.         sti
  912.         test    al,MODC                 ; test if carrier still present
  913.         jnz     comm_output_15          ; continue if so
  914.         mov     ax,-1                   ; flag as no carrier
  915.         jmp     comm_output_90          ; and exit
  916. comm_output_15:
  917.         test    al,MOCT                 ; test if ready to receive the output
  918.         jnz     comm_output_20          ; continue if so
  919.         call    time_tick               ; timeout?
  920.         jnz     comm_output_10          ; else loop
  921.         mov     ax,1                    ; else flag as timeout
  922.         jmp     comm_output_90          ; and exit
  923. ;
  924. comm_output_20:
  925.         call    time_start              ; full max allowed
  926.         mov     dx,cport                ; get base port
  927.         add     dx,STAT
  928. comm_output_30:
  929.         cli
  930.         in      al,dx                   ; get current status
  931.         sti
  932.         and     al,STTX+STTH            ; test if ready to output
  933.         cmp     al,STTX+STTH
  934.         jz      comm_output_40          ; done if so
  935.         call    time_tick               ; timeout?
  936.         jnz     comm_output_30          ; else loop
  937.         mov     ax,1                    ; else flag as timeout
  938.         jmp     comm_output_90          ; and exit
  939. comm_output_40:
  940.         mov     dx,cport                ; get base port
  941.         add     dx,DATA                 ; get data port
  942.         mov     al,[bp+6]               ; get char to output
  943.         out     dx,al                   ; send it out
  944.         xor     ax,ax                   ; flag as no error
  945.         mov     prime,0                 ; we are primed
  946.         jmp     comm_output_90          ; and exit
  947. ;
  948. comm_output_50:
  949.         cli                             ; no interruptions please
  950.         cmp     prime,1                 ; need priming?
  951.         je      comm_output_70          ; output char manually if so
  952. comm_output_52:
  953.         cmp     no_carrier,1            ; loss of carrier?
  954.         jne     comm_output_60
  955.         mov     ax,-1                   ; flag as no carrier
  956.         jmp     comm_output_89
  957. comm_output_60:
  958.         call    time_start              ; full timeout allowed
  959. comm_output_62:
  960.         cli
  961.         cmp     ocount,OBUFFFULL        ; test if buffer is full
  962.         jb      comm_output_64          ; continue if not
  963.         sti
  964.         call    time_tick               ; timeout?
  965.         jnz     comm_output_62          ; and try again if not timeout
  966.         mov     ax,1                    ; flag as a timeout
  967.         jmp     comm_output_89
  968. ;
  969. comm_output_64:
  970.         mov     al,[bp+6]               ; get char to output
  971.         lea     si,obuffer              ; point to buffer
  972.         mov     bx,oputptr              ; get index pointer
  973.         mov     [si][bx],al             ; store it
  974.         inc     bx                      ; bump to next location
  975.         and     bx,OBUFFMASK            ; adjust for circular buffer
  976.         mov     oputptr,bx              ; store for later
  977.         inc     ocount                  ; bump output count
  978.         jmp     comm_output_89          ; exit
  979. ;
  980. comm_output_70:
  981.         cmp     ocount,0                ; is buffer empty?
  982.         jnz     comm_output_52          ; store in buffer if not
  983.         call    time_start              ; full max allowed
  984. comm_output_72:
  985.         sti
  986.         mov     al,cmstat               ; get status
  987. IF DCDW ;*********************************************************************
  988.         jmp     comm_output_75          ; DCDW: skip DCD test
  989. ENDIF   ;*********************************************************************
  990.         test    al,MODC                 ; test if carrier still present
  991.         jnz     comm_output_75          ; continue if so
  992.         mov     ax,-1                   ; flag as no carrier
  993.         jmp     comm_output_90          ; and exit
  994. comm_output_75:
  995.         test    al,MOCT                 ; test if ready to receive the output
  996.         jnz     comm_output_80          ; continue if so
  997.         call    time_tick               ; timeout?
  998.         jnz     comm_output_72          ; else loop
  999.         mov     ax,1                    ; else flag as timeout
  1000.         jmp     comm_output_90          ; and exit
  1001. ;
  1002. comm_output_80:
  1003.         mov     al,clstat               ; get current status
  1004.         and     al,STTX+STTH            ; test if ready to output
  1005.         cmp     al,STTX+STTH
  1006.         jz      comm_output_85          ; done if so
  1007.         call    time_tick               ; timeout?
  1008.         jnz     comm_output_80          ; else loop
  1009.         mov     ax,1                    ; else flag as timeout
  1010.         jmp     comm_output_89          ; and exit
  1011. comm_output_85:
  1012.         cli                             ; no interruptions
  1013.         mov     dx,cport                ; get base port
  1014.         add     dx,DATA                 ; get data port
  1015.         mov     al,[bp+6]               ; get char to output
  1016.         out     dx,al                   ; send it out
  1017.         xor     ax,ax                   ; flag as no error
  1018.         mov     prime,0                 ; we are primed
  1019. ;
  1020. comm_output_89:
  1021.         sti                             ; alive again
  1022. ;
  1023. comm_output_90:
  1024.         pop     si                      ; restore c registers
  1025.         pop     di
  1026.         pop     ds
  1027.         pop     es
  1028.         pop     bp                      ; restore stack frame
  1029.         ret
  1030. ;
  1031. _dmcomm_output  endp
  1032.  
  1033.  
  1034.  
  1035. _dmcomm_wait    proc    far
  1036. ;
  1037. ;==========================
  1038. ;      Comm Port Wait
  1039. ;==========================
  1040. ; Procedure:    1. If not interrupt then exit
  1041. ;               2. If no carrier then exit
  1042. ;               3. If output buffer not empty, goto 2
  1043. ;               4. Exit
  1044. ; Entry:        None
  1045. ; Return:       AX = -1 if no carrier
  1046. ;               AX = 0 if all ok
  1047. ;               AX = 1 if timeout
  1048. ;
  1049.         push    es                      ; save callers registers
  1050.         push    ds
  1051.         push    di
  1052.         push    si
  1053.         mov     ax,cs                   ; access storage
  1054.         mov     ds,ax
  1055. ;
  1056. ; Dispatch based on access type
  1057. ;
  1058.         cmp     usint,1                 ; dispatch
  1059.         je      comm_wait_05
  1060.         ja      comm_wait_50
  1061. ;
  1062. ; Process via Fossil
  1063. ;
  1064. comm_wait_00:
  1065. IF DCDW ;*********************************************************************
  1066.         jmp     comm_wait_02            ; DCDW: skip DCD test
  1067. ENDIF   ;*********************************************************************
  1068.         mov     ah,BCSTAT               ; read the registers
  1069.         mov     dx,commid               ; get port id
  1070.         int     BIOS                    ; get the status
  1071.         and     al,MODC                 ; test for carrier
  1072.         jnz     comm_wait_02
  1073.         mov     ax,-1                   ; flag as no carrier
  1074.         jmp     comm_wait_90            ; and exit
  1075. comm_wait_02:
  1076.         mov     ah,BCWAIT               ; wait for comm output complete
  1077.         mov     dx,commid               ; port id
  1078.         int     BIOS
  1079.         jmp     comm_wait_90            ; exit
  1080. ;
  1081. ; Read ports directly
  1082. ;
  1083. comm_wait_05:
  1084.         mov     bx,0                    ; full max allowed
  1085.         mov     dx,cport                ; get base port
  1086.         add     dx,MODM
  1087. comm_wait_10:
  1088. IF DCDW ;*********************************************************************
  1089.         jmp     comm_wait_15            ; DCDW: skip DCD test
  1090. ENDIF   ;*********************************************************************
  1091.         cli
  1092.         in      al,dx                   ; get current status
  1093.         sti
  1094.         test    al,MODC                 ; test if carrier still present
  1095.         jnz     comm_wait_15            ; continue if so
  1096.         mov     ax,-1                   ; flag as no carrier
  1097.         jmp     comm_wait_90            ; and exit
  1098. comm_wait_15:
  1099.         mov     ax,0                    ; else flag as ok
  1100.         jmp     comm_wait_90            ; and exit
  1101. ;
  1102. ;
  1103. comm_wait_50:
  1104.         call    time_start              ; full timeout allowed
  1105.         cmp     no_carrier,1            ; loss of carrier?
  1106.         jne     comm_wait_60
  1107.         mov     ax,-1                   ; flag as no carrier
  1108.         jmp     comm_wait_90
  1109. comm_wait_60:
  1110.         cmp     ocount,0                ; test if buffer is empty
  1111.         je      comm_wait_70            ; exit all done if so
  1112.         call    time_tick               ; timeout?
  1113.         jnz     comm_wait_60            ; and try again if not timeout
  1114.         mov     ax,1                    ; flag as a timeout
  1115.         jmp     comm_wait_90
  1116. ;
  1117. comm_wait_70:
  1118.         mov     ax,0                    ; no errors
  1119. ;
  1120. ;
  1121. comm_wait_90:
  1122.         pop     si                      ; restore c registers
  1123.         pop     di
  1124.         pop     ds
  1125.         pop     es
  1126.         ret
  1127. ;
  1128. _dmcomm_wait    endp
  1129.  
  1130.  
  1131.  
  1132. _dmcomm_iflush  proc    far
  1133. ;
  1134. ;==========================
  1135. ;   Comm Port Flush Input
  1136. ;==========================
  1137. ; Procedure:    1. Reset all input parms
  1138. ;               2. If RTS down, bring it back up
  1139. ;               3. If XOFF send, send XON
  1140. ;               4. Exit
  1141. ; Entry:        None
  1142. ; Return:       None
  1143. ;
  1144.         push    es                      ; save C registers
  1145.         push    ds
  1146.         push    di
  1147.         push    si
  1148.         mov     ax,cs
  1149.         mov     ds,ax
  1150. ;
  1151. ; Dispatch based on access type
  1152. ;
  1153.         cmp     usint,1                 ; dispatch
  1154.         je      comm_if_90
  1155.         ja      comm_if_10              ; ignore if not
  1156. ;
  1157. ; Process via Fossil
  1158. ;
  1159. comm_if_00:
  1160.         call    _dmcomm_status          ; test if character available
  1161.         cmp     ax,-1                   ; no carrier?
  1162.         je      comm_if_90              ; exit if so
  1163.         cmp     al,1                    ; char available
  1164.         jne     comm_if_90              ; exit if not
  1165. ;
  1166.         mov     ah,BCIN                 ; input a character
  1167.         mov     dx,commid               ; get port id
  1168.         int     BIOS                    ; get the character
  1169.         jmp     comm_if_00              ; test if still more to purge
  1170. ;
  1171. ; Int driven code
  1172. ;
  1173. comm_if_10:
  1174.         cli                             ; lock up the world
  1175.         mov     iputptr,0               ; input put pointer
  1176.         mov     igetptr,0               ; input get pointer
  1177.         mov     icount,0                ; buffer is empty
  1178. ;
  1179.         cmp     no_rts,1                ; RTS taken down?
  1180.         jne     comm_if_20              ; skip if not
  1181.         mov     dx,cport                ; Set DTR & RTS to allow data
  1182.         add     dx,MCRR
  1183.         mov     al,MCRT+MCDT
  1184.         out     dx,al
  1185.         jmp     comm_if_80
  1186. ;
  1187. comm_if_20:
  1188.         cmp     no_xoff,1               ; Have sent an XOFF?
  1189.         jne     comm_if_80              ; skip if not
  1190.         mov     al,XON                  ; Else bring it back up
  1191.         call    comm_char
  1192. ;
  1193. comm_if_80:
  1194.         sti                             ; alive again
  1195. ;
  1196. ; Exit all done
  1197. ;
  1198. comm_if_90:
  1199.         pop     si                      ; restore c registers
  1200.         pop     di
  1201.         pop     ds
  1202.         pop     es
  1203.         ret
  1204. ;
  1205. _dmcomm_iflush  endp
  1206.  
  1207.  
  1208. _dmcomm_oflush  proc    far
  1209. ;
  1210. ;==========================
  1211. ;  Comm Port Output Flush
  1212. ;==========================
  1213. ; Procedure:    1. Exit if not INT driven
  1214. ;               2. Reset all output pointers
  1215. ;               3. Set the prime flag
  1216. ; Entry:        None
  1217. ; Return:       None
  1218. ;
  1219.         push    es                      ; save C registers
  1220.         push    ds
  1221.         push    di
  1222.         push    si
  1223.         mov     ax,cs
  1224.         mov     ds,ax
  1225. ;
  1226. ; Dispatch based on access type
  1227. ;
  1228.         cmp     usint,1                 ; dispatch
  1229.         je      comm_of_90
  1230.         ja      comm_of_10
  1231. ;
  1232. ; Process via Fossil
  1233. ;
  1234. comm_of_00:
  1235.         mov     ah,BCFOUT               ; flush output
  1236.         mov     dx,commid               ; port id
  1237.         int     BIOS
  1238.         jmp     comm_of_90              ; exit
  1239. ;
  1240. ; Int driven code
  1241. ;
  1242. comm_of_10:
  1243. ;
  1244.         cli                             ; lock up the world
  1245.         mov     oputptr,0               ; output put pointer
  1246.         mov     ogetptr,0               ; output get pointer
  1247.         mov     ocount,0                ; buffer is empty
  1248.         mov     prime,1                 ; needs priming
  1249.         sti                             ; alive again
  1250. ;
  1251. comm_of_90:
  1252.         pop     si                      ; restore c registers
  1253.         pop     di
  1254.         pop     ds
  1255.         pop     es
  1256.         ret
  1257. ;
  1258. _dmcomm_oflush  endp
  1259.  
  1260.  
  1261.  
  1262. _dmcomm_isr     proc    far
  1263. ;
  1264. ;==========================
  1265. ;      Comm Port ISR
  1266. ;==========================
  1267. ; Procedure:    1. Test & dispatch interrupt type.
  1268. ;               2. Modem status change:
  1269. ;                  a. If loss of DCD, set flag & goto 1.
  1270. ;                  b. If loss of CTS, set flag & goto 1.
  1271. ;                  c. If CTS not previously lost goto 1.
  1272. ;                  d. Set CTS not lost
  1273. ;                  e. If priming flag false got 1.
  1274. ;                  f. Goto 5.
  1275. ;               3. Line status change:
  1276. ;                  a. Ignore event.
  1277. ;               4. Input available:
  1278. ;                  a. Get input char.
  1279. ;                  b. Store in buffer.
  1280. ;                  c. Adjust pointer.
  1281. ;                  d. If buffer not full, goto 1.
  1282. ;                  e. If hardware handshake, take down RTS.
  1283. ;                  f. Goto 6.
  1284. ;                  g. If software handshake, send XOFF.
  1285. ;                  h. Goto 6.
  1286. ;               5. Output ready:
  1287. ;                  a. If DCD lost then goto 1.
  1288. ;                  b. If CTS lost then goto 5d.
  1289. ;                  c. If output chars then goto 5f.
  1290. ;                  d. Set output priming flag.
  1291. ;                  e. Goto 1.
  1292. ;                  f. Get and output character.
  1293. ;                  g. Adjust output pointer.
  1294. ;                  h. Goto 1.
  1295. ;               6. Pass on to regular ISR.
  1296. ; Entry:        None
  1297. ; Return:       None, all registers preserved
  1298. ;
  1299.         push    ds                      ; save environment
  1300.         push    si
  1301.         push    dx
  1302.         push    bx
  1303.         push    ax
  1304.         mov     ax,cs                   ; access to local data
  1305.         mov     ds,ax
  1306.         sti
  1307. ;
  1308. ; 1. Test & dispatch interrupt type.
  1309. ;
  1310. comm_isr_10:
  1311.         mov     dx,cport                ; get interrupt event
  1312.         add     dx,IINT
  1313.         in      al,dx
  1314.         test    al,IIPD
  1315.         jnz     comm_isr_90
  1316.         jmp     comm_isr_30
  1317. comm_isr_20:
  1318.         mov     dx,cport                ; get interrupt event
  1319.         add     dx,IINT
  1320.         in      al,dx
  1321.         test    al,IIPD
  1322.         jnz     comm_isr_90
  1323. comm_isr_30:
  1324.         and     ax,IIMK
  1325.         lea     si,isr_table            ; dispatch table
  1326.         add     si,ax                   ; index to event
  1327.         call    [si]                    ; dispatch based on event
  1328.         jmp     comm_isr_20             ; repeat till done
  1329. ;
  1330. ; 6. Pass on to regular ISR.
  1331. ;
  1332. comm_isr_90:
  1333.         cmp     passth,0                ; no passthrough?
  1334.         je      comm_isr_95
  1335.         pop     ax                      ; restore environment
  1336.         pop     bx
  1337.         pop     dx
  1338.         pop     si
  1339.         pop     ds
  1340.         jmp     dword ptr cs:[oldint]
  1341. ;
  1342. ; 6. Default ISR exit if no other devices
  1343. ;
  1344. comm_isr_95:
  1345.         mov     dx,iport                ; get port to do EOI
  1346.         add     dx,IEOI
  1347.         mov     al,EOID                 ; value to output
  1348.         out     dx,al
  1349.         pop     ax                      ; restore environment
  1350.         pop     bx
  1351.         pop     dx
  1352.         pop     si
  1353.         pop     ds
  1354.         iret                            ; done processing interrupt
  1355. ;
  1356. ;
  1357. _dmcomm_isr     endp
  1358.  
  1359.  
  1360. comm_modem      proc near
  1361. ;
  1362. ; 2. Modem status change:
  1363. ;
  1364.         mov     dx,cport                ; get modem status
  1365.         add     dx,MODM
  1366.         in      al,dx
  1367.         mov     cmstat,al               ; save it
  1368. ;
  1369. ; 2a. If loss of DCD, set flag & goto 1.
  1370. ;
  1371.         test    al,MODC                 ; test for loss of carrier
  1372.         jnz     comm_modem_b
  1373. IF DCDW ;*********************************************************************
  1374.         jmp     comm_modem_b            ; DCDW: skip DCD flagging
  1375. ENDIF   ;*********************************************************************
  1376.         mov     no_carrier,1            ; flag carrier lost
  1377.         ret                             ; and exit
  1378. ;
  1379. ; 2b. If loss of CTS, set flag & goto 1.
  1380. ;
  1381. comm_modem_b:
  1382.         test    handsh,2                ; test if hardware handshaking?
  1383.         jnz     comm_modem_b2           ; continue if so
  1384.         ret                             ; else ignore it
  1385. ;
  1386. comm_modem_b2:
  1387.         test    al,MOCT                 ; test for loss of CTS
  1388.         jnz     comm_modem_c
  1389.         mov     no_cts,1                ; flag CTS lost
  1390.         ret                             ; and exit
  1391. ;
  1392. ; 2c. If CTS not previously lost goto 1.
  1393. ;
  1394. comm_modem_c:
  1395.         cmp     no_cts,1                ; test if we suddenly got CTS
  1396.         je      comm_modem_d            ; exit if no change
  1397.         ret                             ; else we are done
  1398. ;
  1399. ; 2d. Set CTS not lost
  1400. ;
  1401. comm_modem_d:
  1402.         mov     no_cts,0                ; clear flag
  1403. ;
  1404. ; 2e. If priming flag false got 1.
  1405. ;
  1406.         cmp     prime,1                 ; needs priming?
  1407.         je      comm_modem_e            ; do it if so
  1408.         ret                             ; else all done
  1409. ;
  1410. ; 2f. Goto 5.
  1411. ;
  1412. comm_modem_e:
  1413.         jmp     comm_tx                 ; go transmit a character
  1414. ;
  1415. comm_modem      endp
  1416.  
  1417.  
  1418. comm_line       proc near
  1419. ;
  1420. ; 3. Line status change:
  1421. ;
  1422.         mov     dx,cport                ; get line status port
  1423.         add     dx,STAT
  1424.         in      al,dx                   ; get the data
  1425.         mov     clstat,al               ; save it
  1426.         ret                             ; ignore the errors or events
  1427. ;
  1428. comm_line       endp
  1429.  
  1430.  
  1431. comm_rx         proc near
  1432. ;
  1433. ; 4. Input available:
  1434. ; 4a. Get input char.
  1435. ;
  1436.         mov     dx,cport                ; get data port
  1437.         add     dx,DATA
  1438.         in      al,dx                   ; get the data
  1439.         test    handsh,1                ; test if we have software handshaking
  1440.         jz      comm_rx_b               ; skip if not
  1441.         cmp     al,XOFF                 ; test for XOFF
  1442.         jne     comm_rx_a2              ; continue if not
  1443.         mov     no_xon,1                ; else flag as paused
  1444. ;
  1445. comm_rx_a1:
  1446.         ret
  1447. ;
  1448. comm_rx_a2:
  1449.         cmp     al,XON                  ; test if XON
  1450.         jne     comm_rx_b               ; continue if not
  1451.         cmp     no_xon,1                ; was it down?
  1452.         mov     no_xon,0                ; clear it
  1453.         jne     comm_rx_a1              ; exit if it was not already set
  1454. ;
  1455.         cmp     prime,1                 ; needs priming?
  1456.         jne     comm_rx_a1              ; exit if not
  1457.         jmp     comm_tx                 ; else go transmit a character
  1458. ;
  1459. ; 4b. Store in buffer.
  1460. ;
  1461. comm_rx_b:
  1462.         lea     si,ibuffer              ; point to buffer
  1463.         mov     bx,iputptr              ; get index pointer
  1464.         mov     [si][bx],al             ; store it
  1465. ;
  1466. ; 4c. Adjust pointer.
  1467. ;
  1468.         inc     bx                      ; bump to next location
  1469.         and     bx,IBUFFMASK            ; adjust for circular buffer
  1470.         mov     iputptr,bx              ; store for later
  1471.         inc     icount                  ; bump counter
  1472. ;
  1473. ; 4d. If buffer not full, goto 1.
  1474. ;
  1475.         cmp     icount,IBUFFFULL        ; test if buffer is now full
  1476.         jae     comm_rx_e               ; take down RTS if full
  1477.         ret                             ; else done
  1478. ;
  1479. ; 4e. Take down RTS.
  1480. ; 4f. Goto 1.
  1481. ;
  1482. comm_rx_e:
  1483.         test    handsh,2                ; hardware handshake?
  1484.         jz      comm_rx_g               ; skip if not
  1485.         mov     no_rts,1                ; flag rts as down
  1486.         mov     dx,cport                ; get modem control port
  1487.         add     dx,MCRR
  1488.         mov     al,MCDT+MCO2            ; set DTR true, RTS false
  1489.         out     dx,al
  1490.         ret                             ; and exit
  1491. ;
  1492. ; 4g. Send and XOFF.
  1493. ; 4h. Goto 1.
  1494. ;
  1495. comm_rx_g:
  1496.         test    handsh,1                ; software handshake?
  1497.         jz      comm_rx_h               ; skip if not
  1498.         cmp     no_xoff,1               ; already down?
  1499.         je      comm_rx_h               ; skip if so
  1500.         mov     no_xoff,1               ; flag as paused
  1501.         mov     dx,cport                ; get modem data port
  1502.         add     dx,DATA
  1503.         mov     al,XOFF                 ; send the XOFF
  1504.         call    comm_char
  1505. ;
  1506. comm_rx_h:
  1507.         ret                             ; and exit
  1508. ;
  1509. comm_rx         endp
  1510.  
  1511.  
  1512. comm_tx         proc near
  1513. ;
  1514. ; 5. Output ready:
  1515. ; 5a. If DCD lost then goto 1.
  1516. ;
  1517.         cmp     no_carrier,1            ; test for loss of carrier
  1518.         jne     comm_tx_b               ; continue if not
  1519.         ret                             ; else exit
  1520. ;
  1521. ; 5b. If CTS lost then goto 5d.
  1522. ;
  1523. comm_tx_b:
  1524.         cmp     no_cts,1                ; test for loss of CTS
  1525.         je      comm_tx_d               ; flag prime needed if so
  1526. ;
  1527. ; 5c. If output chars then goto 5f.
  1528. ;
  1529.         lea     si,obuffer              ; point to output buffer
  1530.         mov     bx,ogetptr              ; get output pointer
  1531.         cmp     ocount,0                ; test if empty
  1532.         jne     comm_tx_f               ; output char if not
  1533. ;
  1534. ; 5d. Set output priming flag.
  1535. ; 5e. Goto 1.
  1536. ;
  1537. comm_tx_d:
  1538.         mov     prime,1                 ; set prime needed
  1539.         ret                             ; and exit
  1540. ;
  1541. ; 5f. Get and output character.
  1542. ;
  1543. comm_tx_f:
  1544.         mov     dx,cport                ; get data port
  1545.         add     dx,DATA
  1546.         mov     al,[si][bx]             ; get character to output
  1547.         out     dx,al                   ; output it
  1548. ;
  1549. ; 5g. Adjust output pointer.
  1550. ; 5h. Goto 1.
  1551. ;
  1552.         inc     bx                      ; bump get pointer
  1553.         and     bx,OBUFFMASK            ; adjust for circular buffer
  1554.         mov     ogetptr,bx              ; store it back for later
  1555.         dec     ocount                  ; drop output count
  1556.         ret                             ; exit all done
  1557. ;
  1558. comm_tx         endp
  1559.  
  1560.  
  1561. comm_char       proc near
  1562. ;
  1563. ;==========================
  1564. ;    Send a Char to Comm
  1565. ;==========================
  1566. ; Procedure:    1. Wait for TX empty
  1567. ;               2. Send the char
  1568. ;               3. Exit
  1569. ; Entry:        AL contains char
  1570. ; Return:       None
  1571. ;
  1572.         push    dx                      ; save
  1573.         mov     ah,al                   ; save the char
  1574. ;
  1575.         mov     dx,cport                ; get base port
  1576.         add     dx,STAT
  1577. comm_char_10:
  1578.         in      al,dx                   ; get current status
  1579.         and     al,STTX+STTH            ; test if ready to output
  1580.         cmp     al,STTX+STTH
  1581.         jnz     comm_char_10            ; loop if not
  1582. ;
  1583.         mov     dx,cport                ; get base port
  1584.         add     dx,DATA
  1585.         mov     al,ah                   ; restore char
  1586.         out     dx,al                   ; and send it
  1587. ;
  1588.         pop     dx                      ; restore
  1589.         ret                             ; else exit
  1590.  
  1591. comm_char       endp
  1592.  
  1593.  
  1594. time_start      proc    near
  1595. ;
  1596. ;==========================
  1597. ;    Start Timeout Timer
  1598. ;==========================
  1599. ; Procedure:    1. Set timer values
  1600. ;               2. Exit
  1601. ; Entry:        None
  1602. ; Return:       None
  1603. ;
  1604.         mov     cs:count1,1000H         ; Init timer values
  1605.         mov     cs:count2,1000H
  1606.         ret
  1607. ;
  1608. time_start      endp
  1609.  
  1610.  
  1611. time_tick       proc    near
  1612. ;
  1613. ;==========================
  1614. ;  Tick the Timeout Timer
  1615. ;==========================
  1616. ; Procedure:    1. Decrement timer
  1617. ;               2. Flag if timeout
  1618. ;               3. Exit
  1619. ; Entry:        None
  1620. ; Return:       zf set if timeout
  1621. ;
  1622.         dec     cs:count2               ; One less here
  1623.         jnz     time_tick_90            ; Exit if not expired
  1624. ;
  1625.         mov     cs:count2,1000H         ; Reset this count
  1626.         dec     cs:count1               ; One less in upper timer
  1627.                                         ; Action sets the flag
  1628. ;
  1629. time_tick_90:
  1630.         ret                             ; Exit with ZF set if timeout
  1631. ;
  1632. time_tick       endp
  1633.  
  1634.  
  1635. DMIOSEG ends
  1636. END
  1637.  
  1638.